const express = require('express');
const app = express();

app.use(express.static(__dirname));

app.get('/test', (req, res) => {
  res.send({
    name: 'ahhh'
  });
});

app.listen(7777);

/*
GET ws://localhost:8888/ HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: AIYDwZbTCbAy8rZ7JCwz6w==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
\r\n
\r\n
*/
const net = require('net');
const crypto = require('crypto');
const CODE = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';/**←协议规定好的*/

const server = net.createServer((socket) => {
  // once来自于EventEmitter on once
  // 这里用once 因为只用于握手时 看它是不是要升级成websocket协议
  // 如果不是 就关闭连接 不用在维持连接 再等客户端继续发送数据了
  socket.once('data', (data) => {
    data = data.toString();
    if(data.match(/Upgrade: websocket/)){
      let rows = data.split('\r\n').slice(1)

      const headers = {};
      rows.reduce((memo, item) => {
        let [key, value] = item.split(': ');
        memo[key] = value;
        return memo
      },headers);
      console.log('headers:',headers);

      if(headers['Sec-WebSocket-Version'] === '13'){
        const secWebSocketKey = headers['Sec-WebSocket-Key'];
        const secWebSocketAccept = crypto.createHash('sha1').update(secWebSocketKey + CODE).digest('base64');
        console.log('secWebSocketAccept:',secWebSocketAccept);

        const response = [
          'HTTP/1.1 101 Switching Protocols',
          'Upgrade: websocket',
          `Sec-WebSocket-Accept: ${secWebSocketAccept}`,
          'Connection: Upgrade',
          '\r\n'
        ].join('\r\n'); //←要有两个 \r\n 客户端才知道是响应结束了

        console.log('response:',response);

        socket.write(response);
        // 后所有格式都是基于websocket协议的
        socket.on('data', function (buffers) { // data默认是一个buffer
          /*
            1             1 2             2 3             3 4             4
            0                   1                   2                   3
            0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
           +-+-+-+-+-------+-+-------------+-------------------------------+
           |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
           |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
           |N|V|V|V|       |S|             |   (if payload len==126/127)   |
           | |1|2|3|       |K|             |                               |
           +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
           |     Extended payload length continued, if payload len == 127  |
           + - - - - - - - - - - - - - - - +-------------------------------+
           | Extended payload (continued)  |Masking-key, if MASK set to 1  |
           +-------------------------------+-------------------------------+
           | Masking-key (continued)       |          Payload Data         |
           +-------------------------------- - - - - - - - - - - - - - - - +
           :                     Payload Data continued ...                :
           + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
           |                     Payload Data continued ...                |
           +---------------------------------------------------------------+
          */
          const fin = buffers[0]/*←第一个字节*/ & 0b10000000 == 0b10000000; // 与运算有一个是0就是0 只有都是1的情况才是1
          const opcodo/*←操作码*/ = buffers[0] & 0b00001111;
          console.log('opcodo:',opcodo);
          const isMasked = buffers[1] & 0b100000000 === 0b100000000;//是否进行了掩码
          let payloadLength = buffers[1] & 0b01111111;//取得负载数据的长度
          console.log('payloadLength:',payloadLength); // 5 ←hello
          /** 这里没有对126 127进行判断 默认客户端发送的一定是0-125之间的*/

          let payload;
          if (payloadLength <= 125) {
            if (isMasked) {
              const mask = buffers.slice(2, 6);//掩码
              payload = buffers.slice(6, 6 + payloadLength);//负载数据
              unmask(payload, mask);
            } else {
              payload = buffers.slice(2);
            }
          } else if (payloadLength == 126) {
            payloadLength = buffers.slice(2,4)
            //todo
          }else if(payloadLength == 127){
            payloadLength = buffers.slice(2,10)
            //todo
          }


          const response = Buffer.alloc(2 + payload.length);

          // 第一个字节返回
          response[0] = opcodo | 0b10000000;
          // 第二个字节
          response[1] = payloadLength; // 高位我们本来就像返回0 故直接 = payloadLength
          payload.copy(response, 2); //payload拷贝到response里去 拷到response[2]+
          socket.write(response);
        });
      }
    }
  });

  socket.on('end', function () {
    console.log('end');
  });
  socket.on('close', function () {
    console.log('close');
  });
  socket.on('error', function (error) {
    console.log(error);
  });
});

function unmask(buffer, mask) {
  const length = buffer.length;
  for (let i = 0; i < length; i++) {
    buffer[i] ^=/*←异或*/ mask[i % 4]; //小技巧: %4和 &3是一个意思
  }
}

server.listen(8888);
